package main;

import gui.TerminalPanel;

import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;
import java.io.IOException;
import java.io.InputStream;
import java.net.InetAddress;
import java.net.Socket;
import java.nio.charset.Charset;

public class Client implements Runnable, ActionListener, KeyListener {
	private TerminalPanel myTerminal;
	private Socket socket;
	int outPort = 0;
	private InetAddress ipaddr = null;
	
	public Client(Socket socket)
	{
		this.socket = socket;
		myTerminal = new TerminalPanel();
		myTerminal.setClient(this);
		MainWindow.instance.addTerminal(myTerminal);
		ipaddr = socket.getInetAddress();
		
		Thread thread = new Thread(this);
		thread.start();
	}
	
	public boolean sendBack(String text)
	{
		if(outPort == 0) return false;
		
		if(text.length() == 3)
		{
			if(Character.isDigit(text.charAt(0))
				&& Character.isDigit(text.charAt(1))
				&& Character.isDigit(text.charAt(2)))
			{
				text = text + " ";
			}
		}
		
		try {
			Socket ss = new Socket(ipaddr, outPort);
			byte[] buffer = text.getBytes("US-ASCII");
			byte[] wide = new byte[2 * buffer.length];
			
			for(int i = 0; i < buffer.length; ++i)
			{
				wide[i * 2] = buffer[i];
				wide[i * 2 + 1] = 0;
			}
			
			ss.getOutputStream().write(wide);
			
			ss.close();
			return true;
		} catch (IOException e) {
			myTerminal.appendLine("<GeoTerminal> Failed to send message!");
			return false;
		}
	}
	
	@Override
	public void run() {
		try {
			InputStream is = socket.getInputStream();
			int errors = 0;
			
			while(true)
			{
				byte[] buffer; // = new byte[1024];
				byte[] single = new byte[1];
				//int i = 0;
				is.read(single, 0, 1);
				int msgType = single[0];
				
				if(msgType == 0)
				{
					//is.skip(is.available());
					errors++;
					Thread.sleep(100);
					if(errors > 10)
					{
						MainWindow.instance.removeTerminal(myTerminal);
						return;
					}
					continue;
				}
				
				is.read(single, 0, 1);
				int msgLen = single[0];
				
				if(msgLen == 0)
				{
					//is.skip(is.available());
					errors++;
					Thread.sleep(100);
					if(errors > 10)
					{
						MainWindow.instance.removeTerminal(myTerminal);
						return;
					}
					continue;
				}
				
				errors = 0;
				
				buffer = new byte[msgLen];
				is.read(buffer, 0, msgLen);
				
				String text = new String(buffer, Charset.forName("US-ASCII"));
				/*
				int spaces = 0;
				for(i = text.length() - 1; i > 0; --i)
				{
					if(text.charAt(i) != ' ' && text.charAt(i) != '\0') break;
					spaces++;
				}
				
				text = text.substring(0, text.length() - spaces);
				*/
				if(msgType == 2)
					MainWindow.instance.setTabTitle(myTerminal, text);
				else if(msgType == 3)
				{
					outPort = Integer.parseInt(text.trim());
					myTerminal.setInputEnabled(outPort > 0);
				}
				else if(msgType == 1)
					myTerminal.appendLine(text);
				
			}
		} catch (IOException e) {
			MainWindow.instance.removeTerminal(myTerminal);
		} catch (InterruptedException e) {
			MainWindow.instance.removeTerminal(myTerminal);
		}
	}

	@Override
	public void actionPerformed(ActionEvent arg0) {
		if(sendBack(myTerminal.getInputText()))
		{
			myTerminal.appendLine("> " + myTerminal.getInputText() + "\n ");
			myTerminal.clearInputText();
		}
	}

	@Override
	public void keyPressed(KeyEvent arg0) {
		// TODO Auto-generated method stub
		
	}

	@Override
	public void keyReleased(KeyEvent arg0) {
		if(arg0.getKeyCode() == KeyEvent.VK_ENTER)
		{
			if(sendBack(myTerminal.getInputText()))
			{
				myTerminal.appendLine("> " + myTerminal.getInputText() + "\n ");
				myTerminal.clearInputText();
			}
		}
		
	}

	@Override
	public void keyTyped(KeyEvent arg0) {
		// TODO Auto-generated method stub
		
	}
}
